/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pa165.dominatingspecies.dao.impl;

import pa165.dominating.species.dao.UserDAO;
import pa165.dominatingspecies.dao.common.Validator;
import pa165.dominating.species.exceptions.DataStorageException;
import pa165.dominating.species.exceptions.EntityException;

import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;

import org.springframework.stereotype.Repository;
import pa165.dominating.species.entities.User;

/**
 *
 * @author Filip Dinh
 */
@Repository
public class UserDAOImpl implements UserDAO, Serializable {

    @PersistenceContext
    private EntityManager entityManager;

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public void setEntityManager(final EntityManager em) {
        this.entityManager = em;
    }

    @Override
    public void createUser(User user) {
        Validator.validateEntityManager(entityManager);
        Validator.validateNewEntity(user);

        if (user.getLogin().isEmpty()) {
            throw new EntityException("The user has no login.");
        }
        if (user.getPassword().isEmpty()) {
            throw new EntityException("The user has no password.");
        }

        try {
            entityManager.persist(user);
        } catch (PersistenceException e) {
            throw new DataStorageException("An error has occurred while creating new User", e);
        }
    }

    @Override
    public void updateUser(User user) {
        Validator.validateEntityManager(entityManager);
        Validator.validateUpdatedEntity(user);

        if (user.getLogin().isEmpty()) {
            throw new EntityException("The user has no login.");
        }
        if (user.getPassword().isEmpty()) {
            throw new EntityException("The user has no password.");
        }

        try {
            User existingUser = entityManager.find(User.class, user.getId());
            if (existingUser == null) {
                throw new IllegalArgumentException("User with id " + user.getId() + " has not been found in the databse");
            }
            entityManager.merge(user);
        } catch (PersistenceException ex) {
            throw new DataStorageException("An error has occurred while updating user.", ex);
        }
    }

    @Override
    public void deleteUser(User user) {
        Validator.validateEntityManager(entityManager);
        Validator.validateDeleteEntity(user);

        try {
            User existingUser = entityManager.find(User.class, user.getId());
            if (existingUser == null) {
                throw new IllegalArgumentException("User with id " + user.getId() + " has not been found in the databse");
            }
            entityManager.remove(existingUser);
        } catch (PersistenceException e) {
            throw new DataStorageException("An error has occurred while deleting ", e);
        }
    }

    @Override
    public List<User> getAllUsers() {
        EntityManager em = getEntityManager();
        try {
            TypedQuery<User> usersQuery = em.createNamedQuery("getAllUsers", User.class);
            return usersQuery.getResultList();
        } catch (PersistenceException e) {
            throw new DataStorageException("An error has occured when looking for a user entity in database.", e);
        }
    }

    @Override
    public User getUserById(Long id) {
        Validator.validateEntityManager(entityManager);
        Validator.validateGetEntity(id);
        try {
            return entityManager.find(User.class, id);
        } catch (PersistenceException e) {
            throw new DataStorageException("An error has occured when looking for a User entity in database.", e);
        }
    }
    
    @Override
    public User getUserByUserName(String username){
         Validator.validateEntityManager(entityManager);
        try {
            Query q = entityManager.createQuery("SELECT u FROM User u  WHERE u.login = :username");
            q.setParameter("username", username);
            return (User)q.getSingleResult();
        } catch (PersistenceException e) {
            throw new DataStorageException("An error has occurred while retrieving user by user name", e);
        }
    }
}
